﻿using ArtMath.Attribute;
using ArtMath.Component.Line;
using ArtMath.Component.Point;
using ArtMath.Core.Data;
using ArtMath.Core.Helper;
using ArtMath.Data;
using ArtMath.PointCollection;
using ArtMath.Resource;
using System;
using System.ComponentModel;

namespace ArtMath.Component.Vector
{
    /// <summary>
    /// 平行向量
    /// </summary>
    [Serializable]
    public class ParallelVector : VectorBase
    {
        StraightLineBase line;
        bool unlimit;
        public ParallelVector(SketchPad pad, string name, StraightLineBase line, bool addToList = true) : base(pad, name, ToolTypeName.pxxl, addToList)
        {
            AllowFix = false;
            StraightLine = line;
        }
        [MultilingualCategory("Structure"), MultilingualDisplayName("StraightLine"), TypeConverter(typeof(ExpandableObjectConverter))]
        public StraightLineBase StraightLine
        {
            get { return line; }
            set
            {
                line?.OutChildren_Line.Remove(this);
                line = value;
                line?.OutChildren_Line.Add(this);
            }
        }
        public override double NewSlope
        {
            get { return StraightLine.NewSlope; }
        }
        public override double NewPSlope
        {
            get { return StraightLine.NewPSlope; }
        }
        public override bool PointsHaveConstraint
        {
            get { return true; }
        }
        [Browsable(false)]
        public override RPointS RotateCenter
        {
            get
            {
                return base.RotateCenter;
            }

            set
            {
                base.RotateCenter = value;
            }
        }
        [Browsable(false)]
        public override AngleStringX RotateAngle
        {
            get
            {
                return base.RotateAngle;
            }

            set
            {
                base.RotateAngle = value;
            }
        }
        protected override void PointMoving_AsOutChildrenLimit(PointBase movePoint)
        {
            int movcnt = CountMovablePoints();
            switch (movcnt)
            {
                case 0:
                    if (!StraightLine.NewSlope.AlmostEqual(StraightLine.Slope))
                    {
                        throw new PointMovingException(this, OfTranslator2(Resources.JoinLocalizedString("EndPoint", "CannotMove")));
                    }
                    break;
                case 1:
                case 2:
                    PointBase fix, move;
                    if (Point2.Movable)
                    {
                        move = Point2;
                        fix = Point1;
                    }
                    else
                    {
                        move = Point1;
                        fix = Point2;
                    }
                    double[] abc = fix.ToPointD().GetABC(NewSlope);
                    PointD[] pts = CurveIntersection.StraightLineArcIntersection(abc[0], abc[1], abc[2], fix.ToPointD(), fix.DistanceTo(move), 0, Core.Helper.Angle.RadRound);
                    if (pts != null)
                    {
                        unlimit = fix.TempMoveLock = true;
                        try
                        {
                            move.Move(Pad.XYToPxy(move.ToPointD().GetNearestPoint(pts)));
                        }
                        finally
                        {
                            unlimit = fix.TempMoveLock = false;
                        }
                    }
                    break;
            }
        }
        public override PointCollectionBase[] GetInPointMovingRange(PointBase movePoint, Base sender = null)
        {
            switch (CountMovablePoints())
            {
                case 1:
                    if (unlimit) return Universal.GenerateInstanceArray();
                    return new PointCollectionBase[] { new StraightLine((movePoint == Point1 ? Point2 : Point1).NewXY, NewSlope) };
            }
            return base.GetInPointMovingRange(movePoint, sender);
        }
        public override void CreateComponents()
        {
            if (Point1 == null)
            {
                CreateComponents(Resources.Translate("StartPoint"));
            }
            else
            {
                CreateComponents(Resources.Translate("TerminalPoint"), new PointCollectionBase[] { new StraightLine(Point1.ToPointD(), StraightLine.Slope) });
            }
        }
        public override void ComponentBuilding(Base component)
        {
            if (Point1 == null)
            {
                ShowStatus($"{Resources.Translate("Creating")}{Resources.ColonSeparate}{Name}");
                return;
            }
            SpareCoordinate = SpareCoordinate.GetProjectivePoint(Point1.Pxy, StraightLine.PSlope);
            base.ComponentBuilding(component);
        }
    }
}
